//
package raft
//
//import (
//"errors"
//
//pb "github.com/pingcap-incubator/tinykv/proto/pkg/eraftpb"
//)
//
//// ErrStepLocalMsg is returned when try to step a local raft message
//var ErrStepLocalMsg = errors.New("raft: cannot step raft local message")
//
//// ErrStepPeerNotFound is returned when try to step a response message
//// but there is no peer found in raft.Prs for that node.
//var ErrStepPeerNotFound = errors.New("raft: cannot step as peer not found")
//
//// SoftState provides state that is volatile and does not need to be persisted to the WAL.
//type SoftState struct {
//	Lead      uint64
//	RaftState StateType
//}
//
//func (a *SoftState) equal(b *SoftState) bool {
//	return a.Lead == b.Lead && a.RaftState == b.RaftState
//}
//
//// Ready encapsulates the entries and messages that are ready to read,
//// be saved to stable storage, committed or sent to other peers.
//// All fields in Ready are read-only.
//type Ready struct {
//	// The current volatile state of a Node.
//	// SoftState will be nil if there is no update.
//	// It is not required to consume or store SoftState.
//	*SoftState
//
//	// The current state of a Node to be saved to stable storage BEFORE
//	// Messages are sent.
//	// HardState will be equal to empty state if there is no update.
//	pb.HardState
//
//	// Entries specifies entries to be saved to stable storage BEFORE
//	// Messages are sent.
//	Entries []pb.Entry
//
//	// Snapshot specifies the snapshot to be saved to stable storage.
//	Snapshot pb.Snapshot
//
//	// CommittedEntries specifies entries to be committed to a
//	// store/state-machine. These have previously been committed to stable
//	// store.
//	CommittedEntries []pb.Entry
//
//	// Messages specifies outbound messages to be sent AFTER Entries are
//	// committed to stable storage.
//	// If it contains a MessageType_MsgSnapshot message, the application MUST report back to raft
//	// when the snapshot has been received or has failed by calling ReportSnapshot.
//	Messages []pb.Message
//}
//
//// RawNode is a wrapper of Raft.
//type RawNode struct {
//	Raft *Raft
//	// Your Data Here (2A).
//	prevSoftSt *SoftState
//	prevHardSt pb.HardState
//}
//
//// NewRawNode returns a new RawNode given configuration and a list of raft peers.
//func NewRawNode(config *Config) (*RawNode, error) {
//	// Your Code Here (2A).
//	r := newRaft(config)
//	rn := &RawNode{
//		Raft:       r,
//		prevSoftSt: r.softState(),
//		prevHardSt: r.hardState(),
//	}
//	return rn, nil
//}
//
//// Tick advances the internal logical clock by a single tick.
//func (rn *RawNode) Tick() {
//	rn.Raft.tick()
//}
//
//// Campaign causes this RawNode to transition to candidate state.
//func (rn *RawNode) Campaign() error {
//	return rn.Raft.Step(pb.Message{
//		MsgType: pb.MessageType_MsgHup,
//	})
//}
//
//// Propose proposes data be appended to the raft log.
//func (rn *RawNode) Propose(data []byte) error {
//	ent := pb.Entry{Data: data}
//	return rn.Raft.Step(pb.Message{
//		MsgType: pb.MessageType_MsgPropose,
//		From:    rn.Raft.id,
//		Entries: []*pb.Entry{&ent}})
//}
//
//// ProposeConfChange proposes a config change.
//func (rn *RawNode) ProposeConfChange(cc pb.ConfChange) error {
//	data, err := cc.Marshal()
//	if err != nil {
//		return err
//	}
//	ent := pb.Entry{EntryType: pb.EntryType_EntryConfChange, Data: data}
//	return rn.Raft.Step(pb.Message{
//		MsgType: pb.MessageType_MsgPropose,
//		Entries: []*pb.Entry{&ent},
//	})
//}
//
//// ApplyConfChange applies a config change to the local node.
//func (rn *RawNode) ApplyConfChange(cc pb.ConfChange) *pb.ConfState {
//	if cc.NodeId == None {
//		return &pb.ConfState{Nodes: nodes(rn.Raft)}
//	}
//	switch cc.ChangeType {
//	case pb.ConfChangeType_AddNode:
//		rn.Raft.addNode(cc.NodeId)
//	case pb.ConfChangeType_RemoveNode:
//		rn.Raft.removeNode(cc.NodeId)
//	default:
//		panic("unexpected conf type")
//	}
//	return &pb.ConfState{Nodes: nodes(rn.Raft)}
//}
//
//// Step advances the state machine using the given message.
//func (rn *RawNode) Step(m pb.Message) error {
//	// ignore unexpected local messages receiving over network
//	if IsLocalMsg(m.MsgType) {
//		return ErrStepLocalMsg
//	}
//	if pr := rn.Raft.Prs[m.From]; pr != nil || !IsResponseMsg(m.MsgType) {
//		return rn.Raft.Step(m)
//	}
//	return ErrStepPeerNotFound
//}
//
//// Ready returns the current point-in-time state of this RawNode.
//func (rn *RawNode) Ready() Ready {
//	// Your Code Here (2A).
//	r := rn.Raft
//	rd := Ready{
//		Entries:          r.RaftLog.unstableEntries(),
//		CommittedEntries: r.RaftLog.nextEnts(),
//		Messages:         r.msgs,
//	}
//	softSt := r.softState()
//	hardSt := r.hardState()
//	if !softSt.equal(rn.prevSoftSt) {
//		rn.prevSoftSt = softSt
//		rd.SoftState = softSt
//	}
//	if !isHardStateEqual(hardSt, rn.prevHardSt) {
//		rd.HardState = hardSt
//	}
//	rn.Raft.msgs = make([]pb.Message, 0)
//	if !IsEmptySnap(r.RaftLog.pendingSnapshot) {
//		rd.Snapshot = *r.RaftLog.pendingSnapshot
//		r.RaftLog.pendingSnapshot = nil
//	}
//	return rd
//}
//
//// HasReady called when RawNode user need to check if any Ready pending.
//func (rn *RawNode) HasReady() bool {
//	// Your Code Here (2A).
//	r := rn.Raft
//	if hardSt := r.hardState(); !IsEmptyHardState(hardSt) && !isHardStateEqual(hardSt, rn.prevHardSt) {
//		return true
//	}
//	if len(r.RaftLog.unstableEntries()) > 0 ||
//		len(r.RaftLog.nextEnts()) > 0 ||
//		len(r.msgs) > 0 {
//		return true
//	}
//	if !IsEmptySnap(r.RaftLog.pendingSnapshot) {
//		return true
//	}
//	return false
//}
//
//// Advance notifies the RawNode that the application has applied and saved progress in the
//// last Ready results.
//func (rn *RawNode) Advance(rd Ready) {
//	// Your Code Here (2A).
//	if !IsEmptyHardState(rd.HardState) {
//		rn.prevHardSt = rd.HardState
//	}
//	if len(rd.Entries) > 0 {
//		rn.Raft.RaftLog.stabled = rd.Entries[len(rd.Entries)-1].Index
//	}
//	if len(rd.CommittedEntries) > 0 {
//		rn.Raft.RaftLog.applied = rd.CommittedEntries[len(rd.CommittedEntries)-1].Index
//	}
//	rn.Raft.RaftLog.maybeCompact()
//}
//
//// GetProgress return the the Progress of this node and its peers, if this
//// node is leader.
//func (rn *RawNode) GetProgress() map[uint64]Progress {
//	prs := make(map[uint64]Progress)
//	if rn.Raft.State == StateLeader {
//		for id, p := range rn.Raft.Prs {
//			prs[id] = *p
//		}
//	}
//	return prs
//}
//
//// TransferLeader tries to transfer leadership to the given transferee.
//func (rn *RawNode) TransferLeader(transferee uint64) {
//	_ = rn.Raft.Step(pb.Message{MsgType: pb.MessageType_MsgTransferLeader, From: transferee})
//}
